package znet

import (
	"fmt"
	"github.com/1141520944/go-library/library/log"
	"go-library/library/goroutine"
	"net"
	"zinxLearn/pkg/zinx/util"
	"zinxLearn/pkg/zinx/ziface"
)

var _ ziface.IServer = (*ZServer)(nil)

type ZServer struct {
	Name        string
	IPVersion   string
	IP          string
	Port        string
	l           *log.Logger
	Err         chan error
	Router      ziface.IMsgHandler            // server 注册的路由逻辑
	ConnManager ziface.IConnManger            // 连接管理器
	OnConnStart func(conn ziface.IConnection) // 该Server的连接创建时Hook函数
	OnConnStop  func(conn ziface.IConnection) // 该Server的连接断开时的Hook函数
}

func (s *ZServer) Start() {
	goroutine.Submit(func() {
		var (
			addr     *net.TCPAddr
			err      error
			listener *net.TCPListener
		)
		defer func() {
			if err != nil {
				s.l.Infow("[server] err", err.Error())
			}
		}()
		// 启动工作池
		s.Router.StartWorkerPool()

		addr, err = net.ResolveTCPAddr(s.IPVersion, s.IP+":"+s.Port) // tcp 的 Addr
		if err != nil {
			return
		}
		listener, err = net.ListenTCP(s.IPVersion, addr) // 监听服务器地址
		if err != nil {
			return
		}
		//TODO server.go 应该有一个自动生成ID的方法
		var cid uint32
		cid = 0
		s.l.Infow("[server.listen]", "running", "ip", s.IP, "port", s.Port)
		for {
			var (
				conn *net.TCPConn
				cErr error
			)
			if conn, err = listener.AcceptTCP(); err != nil {
				s.l.Infow("[server.conn]  err", cErr.Error())
				continue
			}
			// todo : 设置服务器的最大连接控制，如果超过最大连接控制，那么关闭这次新连接
			if s.ConnManager.Len() >= util.MaxConn {
				conn.Close()
				continue
			}
			// todo: 处理新业务的方法,此时的handler和conn是绑定的
			zconn := NewZConn(s.l, conn, cid, s.Router, s)
			cid++
			goroutine.Submit(func() {
				zconn.Start()
			})
		}
	})

}
func (s *ZServer) Stop() {
	//将其他需要清理的连接信息或者其他信息 也要一并停止或者清理
	s.ConnManager.ClearConn()
}
func (s *ZServer) Server() {
	s.Start()
	// todo: 其他的逻辑控制
	select {}
}
func (s *ZServer) AddRouter(id uint32, router ziface.IRouter) {
	s.Router.AddRouter(id, router)
}
func NewZServer(name string, log *log.Logger, options ...Option) *ZServer {
	z := &ZServer{
		Name:        name,
		l:           log,
		Router:      NewZMsgHandle(),  // 初始化注册路由
		ConnManager: NewConnManager(), // 连接管理器
	}
	for _, option := range options {
		option(z)
	}
	return z
}

type Option func(z *ZServer)

func WitchName(name string) Option {
	return func(z *ZServer) {
		z.Name = name
	}
}
func WithIPVersion(version string) Option {
	return func(z *ZServer) {
		z.IPVersion = version
	}
}
func WithIP(ip string) Option {
	return func(z *ZServer) {
		z.IP = ip
	}
}
func WithPort(port string) Option {
	return func(z *ZServer) {
		z.Port = port
	}
}
func (s *ZServer) GetConnMgr() ziface.IConnManger {
	return s.ConnManager
}

// 设置该Server的连接创建时Hook函数
func (s *ZServer) SetOnConnStart(hookFunc func(ziface.IConnection)) {
	s.OnConnStart = hookFunc
}

// 设置该Server的连接断开时的Hook函数
func (s *ZServer) SetOnConnStop(hookFunc func(ziface.IConnection)) {
	s.OnConnStop = hookFunc
}

// 调用连接OnConnStart Hook函数
func (s *ZServer) CallOnConnStart(conn ziface.IConnection) {
	if s.OnConnStart != nil {
		fmt.Println("---> CallOnConnStart....")
		s.OnConnStart(conn)
	}
}

// 调用连接OnConnStop Hook函数
func (s *ZServer) CallOnConnStop(conn ziface.IConnection) {
	if s.OnConnStop != nil {
		fmt.Println("---> CallOnConnStop....")
		s.OnConnStop(conn)
	}
}
